package com.zzq.demo.generator;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: zhaoziqian
 * @description: TODO
 * @date: 2020/3/8 11:12 下午
 **/
public class MybatisPlusGenerator {

    private String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver" ;
    private String JDBC_URL = "jdbc:mysql://127.0.0.1:3306/kds_auth?autoReconnect=true&useUnicode=true&characterEncoding=utf8" ;
    private String JDBC_USERNAME = "root" ;
    private String JDBC_PASSWORD = "root" ;
    //项目文件夹名称，我的项目名称就是mybatisplus
    private String PROJECT_NAME = "" ;
    // 包前缀，也就是你的代码要生成在那个包底下
    private String BASE_PACKAGE_NAME = "com.zzq.demo.generator" ;
    // 表名称，也就是你要生成那些表的代码，我这里配置了一个表
    private String[] table = {"user"};
    // 模块路径，因为我就一个模块所以路径就是./，如果你的项目有多个模块，那就要指定你的模块名称
    private String modelPath = "" ;

    @Test
    public void generator() {
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        GlobalConfig gc = globalConfig();
        mpg.setGlobalConfig(gc);
        // 数据源配置
        DataSourceConfig dsc = dataSourceConfig();
        mpg.setDataSource(dsc);
        // 策略配置
        StrategyConfig sc = strategyConfig();
        mpg.setStrategy(sc);
        // 包配置
        PackageConfig pc = packageConfig();
        mpg.setPackageInfo(pc);
        // 注入自定义配置
        InjectionConfig ig = injectionConfig();
        mpg.setCfg(ig);
        // 模板配置
        TemplateConfig tc = templateConfig();
        mpg.setTemplate(tc);
        // 执行生成
        mpg.execute();
        System.out.println("生成结束！");
    }

    /**
     * 数据源配置
     *
     * @return 数据源配置
     */
    private DataSourceConfig dataSourceConfig() {
        DataSourceConfig dsc = new DataSourceConfig();
        // 数据源类型orcale和mysql是不一样的
        dsc.setDbType(DbType.MYSQL);
        dsc.setDriverName(JDBC_DRIVER);
        dsc.setUsername(JDBC_USERNAME);
        dsc.setPassword(JDBC_PASSWORD);
        // 驱动名称
        dsc.setUrl(JDBC_URL);
        return dsc;
    }

    /**
     * 数据库表配置
     *
     * @return 数据库表配置
     */
    private StrategyConfig strategyConfig() {
        StrategyConfig sc = new StrategyConfig();
        // 是否大写命名
        sc.setCapitalMode(false);
        // 是否跳过视图
        sc.setSkipView(true);
        // 表名生成策略
        sc.setNaming(NamingStrategy.underline_to_camel);
        // 数据库表字段映射到实体的命名策略, 未指定按照 naming 执行
//        sc.setColumnNaming(NamingStrategy.underline_to_camel);
        // 表前缀
//        sc.setTablePrefix("");
        // 字段前缀
//        sc.setFieldPrefix("");
        // 自定义继承的Entity类全称，带包名
//        sc.setSuperEntityClass(null);
        // 实体】是否为lombok模型
        sc.setEntityLombokModel(true);
        // Boolean类型字段是否移除is前缀
        sc.setEntityBooleanColumnRemoveIsPrefix(false);
        // 生成 @RestController 控制器
        sc.setRestControllerStyle(true);
        // 是否生成实体时，生成字段注解
        sc.setEntityTableFieldAnnotationEnable(true);
        // 自定义继承的Mapper类全称，带包名
        sc.setSuperMapperClass(BaseMapper.class.getName());
        // 自定义继承的Service类全称，带包名
        sc.setSuperServiceClass(IService.class.getName());
        // 需要生成的表
//        sc.setInclude(table);
        // 需要排除的表
        sc.setExclude(null);
        return sc;
    }

    /**
     * 包名配置
     *
     * @return 包名配置
     */
    private PackageConfig packageConfig() {
        PackageConfig pc = new PackageConfig();
        // 父包名。如果为空，将下面子包名必须写全部， 否则就只需写子包名
        pc.setParent(BASE_PACKAGE_NAME);
        pc.setController("controller");
        pc.setEntity("model");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setServiceImpl("service.impl");
//        pc.setXml(null);
        // 路径配置信息
//        pc.setPathInfo();
        return pc;
    }

    /**
     * 模板配置
     *
     * @return 模板配置
     */
    private TemplateConfig templateConfig() {
        TemplateConfig tc = new TemplateConfig();
        tc.setXml(null);
        return tc;
    }

    /**
     * 全局策略配置
     *
     * @return 全局策略配置
     */
    private GlobalConfig globalConfig() {
        GlobalConfig gc = new GlobalConfig();
        // 生成文件的输出目录
        gc.setOutputDir(path() + "/src/main/java");
        // 是否打开输出目录
        gc.setOpen(false);
        // 是否覆盖已有文件
        gc.setFileOverride(true);
        gc.setActiveRecord(true);
        // 是否在xml中添加二级缓存配置
        gc.setEnableCache(true);
        // 开启 BaseResultMap
        gc.setBaseResultMap(true);
        // 开启 baseColumnList
        gc.setBaseColumnList(true);
        // 时间类型对应策略
        gc.setDateType(DateType.TIME_PACK);
        // 开发人员
        gc.setAuthor("zhaoziqian");
        // 开启 swagger2 模式
        gc.setSwagger2(true);
        // 开启 ActiveRecord 模式
        gc.setActiveRecord(false);
        // 自定义文件命名，注意 %s 会自动填充表实体属性！
        gc.setEntityName("%s");
        gc.setIdType(null);
        gc.setMapperName("%sMapper");
        gc.setXmlName("%sMapper");
        gc.setServiceName("%sService");
        gc.setServiceImplName("%sServiceImpl");
        gc.setControllerName("%sController");
        return gc;
    }

    private String path() {
        File file = new File(modelPath);
        return file.getAbsolutePath();
    }

    /**
     * 注入配置
     *
     * @return 注入配置
     */
    private InjectionConfig injectionConfig() {
        InjectionConfig ic = new InjectionConfig() {
            @Override
            public void initMap() {

            }
        };
        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        //自定义配置会被优先输出
        focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ，如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return path() + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        ic.setFileOutConfigList(focList);
        return ic;
    }
}
